//class for update queries function, by Fransiska Putri Wina
#include "Menu_Update_Queries.h"

using namespace std;

//default constructor
Menu_Update_Queries::Menu_Update_Queries() {}

//procedure for solving B3a problem, by Fransiska Putri Wina
void Menu_Update_Queries::B3a(vector<Menu_Item> menu_items,vector<Order_Item>& order_items, vector<Order> orders) {
   cout << "\nAdd a new order item to an existing order\n\n";
   
   /* The following code has been written by Fransiska Putri Wina, solving problem B3a */
   
   char seat;
   int order;
   string menuitem;
   int menuitemid;
   bool exist=false;
   bool first;
   int prodq;
   
   cout << "Add new order item.\n";
   cout << "Please input seat number:\n(A, B, C, D, E, F, G, H)\n>> ";
   cin >> seat;
   
   if(seat == 'A' || seat == 'B' || seat == 'C' || seat == 'D' || seat == 'E' || seat == 'F' || seat == 'G' || seat == 'H')
   {
	   first = true;
	   exist = false;
	   while (!exist) {
		  if (!first) {
			 cout << "Apologies, there does not appear to be an order ID bearing that number.\n";
			 cout << "Please re-input order ID:\n>>";
		  } else {
			 cout << "Please input order ID:\n>>";
			 first = false;
		  }
		  cin >> order;
		  for(int i = 0; i < orders.size(); i++) {
			 if(orders[i].getOrderID() == order) {
				exist = true;
				order = orders[i].getOrderID();
				//break;
			 }
		  }
	   }
	   //order = order_items[order_items.size()-1].getOrderID() + 1; //get the right order item ID -- the succesor of the last order ID
	   
	   first=true;
	   exist=false;
	   while (!exist) {
		  if (!first) {
			 cout << "Apologies, there does not appear to be a menu item bearing that name.\n";
			 cout << "Please re-input menu item name:\n>>";
		  } else {
			 cout << "Please input menu item name:\n>>";
			 first = false;
		  }
		  cin >> menuitem;
		  for(int i = 0; i < menu_items.size(); i++) {
			 if(menu_items[i].get_menu_item_name() == menuitem) {
				exist = true;
				menuitemid = menu_items[i].menuItemId();
				//break;
			 }
		  }
	   }
	   
	   cout << "Please input product quantitiy :\n>>";
	   cin >> prodq;
	   
	   Order_Item temp1(seat, order, menuitemid, prodq);
	   order_items.push_back(temp1);
		sort(order_items.begin(), order_items.end());
	   
	   //cout << seat << " " << order << " " << menuitemid << " " << prodq << endl;
	   cout << "Order item has been added succesfully \n\n";
	   
	   stringstream ss;
	   ss << "You have added a new order item: " << temp1.getMenuItemID() << " in order ID: " << temp1.getOrderID();
	   newOrderItems.push_back(ss.str());
	}
	else
	{
		cout << "\nError: There is no seat ID " << seat << ". Please insert A, B, C, D, E, F, G, or H.\n\n";
	}
   /* End of code written by FPW */
}

//procedure for solving C (delete order item) problem, by Muhammad Ghufron Mahfudhi
void Menu_Update_Queries::C_del_order_item(vector<Menu_Item> menu_items,vector<Order_Item>& order_items) {
   /* MGM delete query: START */
   cout << "\nDelete an order item in the existing order\n\n";

   int orderID;
   cout << "Please input an order ID:\n>> ";
   cin >> orderID;

   cout << "\nHere is the list of order items in order: " << orderID << endl;
   vector<Order_Item> tempOrderItem;
   for(int i = 0; i < order_items.size(); i++)
   {
      if(order_items[i].getOrderID() == orderID)
      {
         tempOrderItem.push_back(order_items[i]);
      }
   }
   if(tempOrderItem.size() == 0)
   {
      cout << "There are no order item with order id: " << orderID << endl << endl;
   }
   else
   {
      string menu[3][tempOrderItem.size()+1];
      menu[0][0] = " Seat";
      menu[1][0] = " Menu Item";
      menu[2][0] = " Quantity";
      for(int i = 0; i < tempOrderItem.size(); i++)
      {
         stringstream s3;
         s3 << " " << tempOrderItem[i].getSeatID();
         menu[0][i+1] = s3.str();
         int j = 0;
         while(j < menu_items.size() && menu_items[j].get_menu_item_id() != tempOrderItem[i].getMenuItemID())
         {
            j++;
         }
         if(j < menu_items.size())
         {
            stringstream s1;
            s1 << " " << menu_items[j].get_menu_item_name() << " $" << menu_items[j].getPrice();
            menu[1][i+1] = s1.str();
         }
         stringstream s2;
         s2 << " " << tempOrderItem[i].getProdQty();
         menu[2][i+1] = s2.str();
      }
      //print
      for(int i = 0; i < 3; i++)
      {
         cout << "|";
         for(int j = 0; j < 20; j++)
         {
            cout << "-";
         }
      }
      cout << "|\n";
      for(int i = 0; i < tempOrderItem.size()+1; i++)
      {
         for(int j = 0; j < 3; j++)
         {
            cout << "|";
            cout << menu[j][i];
            int len = 20 - menu[j][i].size();
            for(int k = 0; k < len; k++)
            {
               cout << " ";
            }
         }
         cout << "|\n";
         if(i == 0 || i == tempOrderItem.size())
         {
            for(int j = 0; j < 3; j++)
            {
               cout << "|";
               for(int k = 0; k < 20; k++)
               {
                  cout << "-";
               }
            }
            cout << "|\n";
         }
         else
         {
            for(int j = 0; j < 3; j++)
            {
               cout << "|";
               for(int k = 0; k < 20; k++)
               {
                  cout << " ";
               }
            }
            cout << "|\n";
         }
      }

      char seatID;
      string menuItem;
      cout << "\nPlease input the seat:\n>> ";
      cin >> seatID;
      cout << "\nPlease input the menu item:\n>> ";
      cin >> menuItem;
      int i = 0;
      int menuID;
      while(i < menu_items.size() && menu_items[i].get_menu_item_name() != menuItem)
      {
         i++;
      }
      if(i < menu_items.size())
      {
         menuID = menu_items[i].get_menu_item_id();
         int j = 0;
         while(j < order_items.size() && (order_items[j].getOrderID() != orderID || order_items[j].getSeatID() != seatID || order_items[j].getMenuItemID() != menuID))
         {
            j++;
         }
         if (j < order_items.size())
         {
            //cout << order_items.size() << endl;
            order_items.erase(order_items.begin() + j);
            //cout << order_items.size() << endl;
            cout << "\nOrder item with order ID " << orderID << ", seat " << seatID << ", and menu item " << menuItem << " have been deleted succesfully.\n\n";

			stringstream ss;
			ss << "You have deleted an order item: " << menuItem << " from order ID: " << orderID;
			newOrderItems.push_back(ss.str());
         }
         else
         {
            cout << "Error: There is no order item with order ID " << orderID << ", seat " << seatID << ", and menu item " << menuItem << ".\n\n";
         }
      }
      else
      {
         cout << "Error: The menu item is not available.\n\n";
      }
      
   }

   /* MGM delete query: END */
}

/* 
      Add a new menu item using an existing recipe to an existing category (MGM B.3 b)
      The following code was modified by Eric Heisler in solving C3f. It now allows user
       to use a new recipe with a new menu item, which means the creation of new 
       ingredients that are being used by the new recipe, which is ultimately being 
       used by the new menu item
      */
void Menu_Update_Queries::B3b_C3f(vector<Category> categories,vector<Recipe>& recipes, vector<Ingredient>& ingredients, vector<Menu_Item>& menu_items) {
   cout << "\nAdd a new menu item to an existing category\n\n";
   
   string category;
   int categoryId;
   int recipeId;
   int menuItemId;
   string menuItemName;
   double menuItemPrice;
   string description = "";
   bool catExist = false;
   bool recExist = false;
   bool showInfoCat = false;
   bool showInfoRec = false;
   
   //input category
   while(!catExist)
   {
      cout << "Please input a category name:\n(enter \"info\" to view the categories)\n>> ";
      cin >> category;
      for(int i = 0; i < categories.size(); i++)
      {
         if(categories[i].get_cat_name() == category)
         {
            catExist = true;
            categoryId = categories[i].get_cat_id();
            cout << endl;
         }
      }
      if(!catExist)
      {
         if(category == "info")
         {
            cout << "Categories: ";
            for(int i = 0; i < categories.size(); i++)
            {
               cout << categories[i].display();
               if(i < categories.size()-1)
               {
                  cout << ", ";
               }
            }
            cout << endl << endl;
            showInfoCat = true;
         }
         else
         {
            cout << "Apologies, there does not appear to be a category.\n\n";
         }
      }            
   }
   //input recipe
   cout << "Do you wish to use a previous recipe, or would you like to create a new one \n(enter 'y' to use previous recipe, enter 'n' to create new one)\n>>";
   string new_recipe = "";
   cin >> new_recipe;
   if(new_recipe=="y" || new_recipe=="Y")
   {
      while(!recExist)
      {
         cout << "Please input a recipe id:\n(enter \"-1\" to view the recipes)\n>> ";
         cin >> recipeId;
         for(int i = 0; i < recipes.size(); i++)
         {
            if(recipes[i].recipeId() == recipeId)
            {
               recExist = true;
               cout << endl;
            }
         }
         if(!recExist)
         {
            if(recipeId == -1)
            {
               cout << "Recipes: ";
               for(int i = 0; i < recipes.size(); i++)
               {
                  recipes[i].displaym();
                  cout << endl;
               }
               cout << endl << endl;
               showInfoRec = true;
            }
            else
            {
               cout << "Apologies, there does not appear to be a recipe bearing that number.\n\n";
            }
         }            
      }
   }
   else if(new_recipe=="n" || new_recipe=="N") 
   {		
      recipeId = recipes[recipes.size()-1].recipeId() + 1;
      cout << "\nPlease enter the instructions for this recipe. Signify the end of the instructions by using '#' as its own word.\n";
      string instr = "";
      string next_word = "";
      while(next_word!="#")
      {
         cin >> next_word;
         if (next_word !="#") {
         	instr+=" " + next_word;
		}
	  }
      cout << "\nAnd who shall be the chef of this recipe \n>>";
      string chef = "";
      cin >> chef;
   
      cout << "\nList the ingredients that this recipe uses.\n(Specify name (one word only), measurement unit (one word only), and amount)\n";
      string name = "";
      string unit = "";
      float amt = 0.0;
   
		cout << " Name: ";
		 cin >> name;
		 cout << " Unit: ";
		 cin >> unit ;
		 cout << " Amount: ";
		 cin >> amt;
		 cout << "\n";
		 ingredients.push_back(Ingredient ( ingredients[ingredients.size()-1].get_ingredient_id()+1, recipeId, amt, unit, name ));
		 stringstream ss;
		 ss << "You have added a new ingredient: " << amt << " " << unit << " of " << name;
		 newIngredients.push_back(ss.str());
		 
      while (true){
		cout << "(use '#' as name to quit)\n";
         cout << " Name: ";
         cin >> name;
		 if(name=="#") break;
         cout << " Unit: ";
         cin >> unit ;
         cout << " Amount: ";
         cin >> amt;
         cout << "\n";
         ingredients.push_back(Ingredient ( ingredients[ingredients.size()-1].get_ingredient_id()+1, recipeId, amt, unit, name ));
		 stringstream ss;
		 ss << "You have added a new ingredient: " << amt << " " << unit << " of " << name;
		 newIngredients.push_back(ss.str());
      } 
   
      recipes.push_back( Recipe ( recipeId, chef, Instructions ( instr )) );
	  stringstream ss2;
	  ss2 << "You have added a new recipe with ID and chef: " << recipeId << " and " << chef;
     newRecipes.push_back(ss2.str());
   }
   //generate menu item id
   /*srand(menu_items.size());
   bool found;
   do
   {
   menuItemId = rand() % 1000 + 2000;
   found = false;
   int i = 0;
   while(i < menu_items.size() && menuItemId != menu_items[i].get_menu_item_id())
   {
      i++;
   }
   if(i < menu_items.size())
   {
      found = true;
   }
   } while(found);*/
   menuItemId = menu_items[menu_items.size()-1].get_menu_item_id() + 1;
   //input menu item name
   cout << "\nPlease input the menu item name:\n(Make sure the food name is 1 word long only)\n>> ";
   cin >> menuItemName;
   //input menu item price
   cout << "\nPlease input the menu item price\n(Exclude dollar symbol)\n>> ";
   cin >> menuItemPrice;
   //input description
   cout << "\nPlease input the menu description:\n(Signal the end of description by using # key as its own word)\n>> ";
   string input;
   while(input != "#")
   {
      cin >> input;
      description += input + " ";
   }
   
   //add the menu item
   Menu_Item menu (menuItemId, categoryId, recipeId, menuItemName, menuItemPrice, Description (description));
   menu_items.push_back(menu);
   newMenuItems.push_back("You have added a new menu item: " + menuItemName);
   cout << "\nMenu item (" << menu.get_menu_item_name() << ") has been added succesfully\n\n\n";
}

void Menu_Update_Queries::B3c(vector<Category>& categories) {
    /* 
    The following code was written by Eric Heisler, and solves problem B3 c
    */
    cout << "\nAdd new categories, (ex. Soups, Salads, Sides).\n\n";
    cout << "Please enter the name of the category you would like to add.\n(Make sure category name is 1 word)\n(Enter -1 to cancel)\n>>";
    string cat_name;
    cin >> cat_name;
    if(cat_name=="-1") {
      cout << "Cancelled.\n\n";
      return;
    }
    Category category (categories[categories.size()-1].get_cat_id()+1, cat_name);
    categories.push_back(category);
	newCategories.push_back("You have added a new category: " + cat_name);
    cout << "Category was successfully added.\n\n";
    /* End of code written by EMH */
}

void Menu_Update_Queries::C3e(vector<Order>& orders) {
      /* The following codes was written by Eric Heisler, and solves problem C3e */
      int order_id = orders[orders.size()-1].getOrderID() + 1;
      string server = "";
      int server_id = 0;
      int table_id = 0;
      string response;
      
      cout << "You are about to be seated.\nWho is your server \n>> ";
      cin >> server_id;
      
      cout << "\nAnd which table are you seated at  (#)\n>> ";
      cin >> table_id;
      cout << "\nWould you like to use the current time  (y/n)\n>> ";
      cin >> response;
      
      if(response == "y" || response == "Y") {
         time_t t = time(0);
         struct tm * curr_time = localtime( &t );
         Date date ( curr_time->tm_year + 1900, (curr_time->tm_mon) + 1, curr_time->tm_mday );
         Time time ( curr_time->tm_hour, curr_time->tm_min );
         Order order ( order_id, server_id, table_id, date, time );
         orders.push_back( order );
		 stringstream ss;
		 ss << "You have added a new order with ID: " << order_id;
		 newOrders.push_back(ss.str());
      }
      else {
         int hour;
         int min;
         int month;
         int day;
         int year;
         int attempt = 1;
         
         while( hour > 23 || hour < 0) {
            if(attempt > 1) cout << "\nInvalid number. Please try again.";
            cout << "\nWhat time is it then \n Hour (#): ";
            cin >> hour;
            attempt++;
         }
         attempt = 1;
         while( min > 59 || min < 0 ) {
            if(attempt > 1) cout << "\nInvalid number. Please try again.";
            cout << "\n Minute (#): ";
            cin >> min;
            attempt++;
         }
         attempt = 1;
         while( day > 31 || day < 1) {
            if(attempt > 1) cout << "\nInvalid number. Please try again.";
            cout << "\n Day (1-31): ";
            cin >> day;
            attempt++;
         }
         attempt = 1;
         while( month > 12 || month < 1 ) {
            if(attempt > 1) cout << "\nInvalid number. Please try again.";
            cout << "\n Month (1-12): ";
            cin >> month;
            attempt++;
         }
         cout << "\n Year: ";
         cin >> year;
         
         Date date ( year, month, day );
         Time time ( hour, min );
         Order order ( order_id, server_id, table_id, date, time );
         orders.push_back( order );
		 stringstream ss;
		 ss << "You have added a new order with ID: " << order_id;
		 newOrders.push_back(ss.str());
      }
      
      cout << "Excellent, you may add to your order whenever you are ready.\n\n";
      /* End of code written by EMH */
}
/*
The following method was written by Eric M Heisler, and solves Part C's delete function
returns the index of the item to be deleted
*/
int Menu_Update_Queries::del_menu_item( vector<Menu_Item> mi ) {
      string menu_item_name = "";
      bool deleted = false;
      int index = -1;

      while(!deleted) {
         cout << "\nEnter the name of the menu item you wish to delete.\n(Enter '?' to view all menu items, and '!' to quit)\n>>";
         cin >> menu_item_name;
         if(menu_item_name == "?") {
            for(int i = 0; i < mi.size(); i++) {
               cout << mi[i].get_menu_item_name() << "\n";
            }
         }
         else if ( menu_item_name == "!" ) return -1;
         for(int i = 0; i < mi.size(); i++) {
            if(mi[i].get_menu_item_name() == menu_item_name) {
               index = i;
               deleted = true;
			   newMenuItems.push_back("You have deleted a menu item: " + menu_item_name);
               break;
            }
         }
         if(!deleted) cout << "Invalid input. There is no menu item bearing that name.\n";
      }
      return index;
}